#include "app_device.h"

static app_buffer_t *up_buffer;
static app_buffer_t *down_buffer;

static uint8_t device_list[10];
static int device_nums = 0;

static pthread_t device_check_thread;

/**
 * @brief 设备模块初始化
 * 1 缓冲区 *2  上 下
 * 2 modbus初始化
 * 3 pool 初始化
 * 4 mqtt 初始化
 *
 */
int app_device_init(void)
{
    //      * 1 缓冲区 *2  上 下
    up_buffer = app_buffer_init(1024);
    down_buffer = app_buffer_init(1024);
    if (up_buffer == NULL || down_buffer == NULL)
    {
        log_error("app_device_init:app_buffer_init error");
        return -1;
    }
    log_info("app_device_init:app_buffer_init ok");
    //  * 2 modbus初始化
    int ret = app_modbus_init(DEV_FILE_NAME);
    if (ret == -1)
    {
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        log_error("app_device_init:app_modbus_init error");
        return -1;
    }
    log_info("app_device_init:app_modbus_init ok");
    //  * 3 pool 初始化
    ret = app_pool_init();
    if (ret == -1)
    {
        log_error("app_device_init:app_pool_init error");
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        app_modbus_destroy();
        return -1;
    }
    log_info("app_device_init:app_pool_init ok");
    //  * 4 mqtt 初始化
    ret = app_mqtt_init();
    if (ret == -1)
    {
        log_error("app_device_init:app_mqtt_init error");
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        app_modbus_destroy();
        app_pool_destroy();
        return -1;
    }
    return 0;
}

/**
 * @brief 把json转换为字节数组
 */
//{"device_id":1,"motor_set_nums":800,"motor_status","on"} ==>
// 01 03 20 01
static int message_jsonToChars(char *json, char *buffer, int buffer_len)
{
    if (buffer_len < 4)
    {
        log_error("buffer is too small ");
    }
    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        perror("json is invalid ");
        return -1;
    }

    cJSON *device_id_cjson = cJSON_GetObjectItem(root, "device_id");
    cJSON *motor_set_nums_cjson = cJSON_GetObjectItem(root, "motor_set_nums");
    cJSON *motor_status_cjson = cJSON_GetObjectItem(root, "motor_status");

    uint8_t device_id = device_id_cjson->valueint;
    uint16_t motor_set_nums = motor_set_nums_cjson->valueint;
    char *motor_status_chr = motor_status_cjson->valuestring;

    buffer[0] = device_id;
    memcpy(buffer + 1, &motor_set_nums, 2);
    buffer[3] = strcmp(motor_status_chr, "on") == 0 ? 1 : 0;

    app_common_printHex("app_message_jsonToChars :", buffer, 4);
    cJSON_Delete(root);
    return 4;
}

/**
 * @brief 把字节数组转换为json
 *   // 01 00 10 01
 *  => {"device_id":1,"motor_speed":16,"motor_status":"on"}
 */
char *message_charsToJson(char *data, int data_len)
{
    // 先把data提取成值
    uint8_t device_id = data[0];
    uint16_t motor_speed = 0;
    memcpy(&motor_speed, data + 1, 2);
    uint8_t motor_status = data[3];

    // cjson结构体 生成json字符串
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "device_id", device_id);
    cJSON_AddNumberToObject(root, "motor_speed", motor_speed);
    cJSON_AddStringToObject(root, "motor_status", motor_status ? "on" : "off");

    char *jsonstr = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    return jsonstr;
}

/**
 * @brief 把deviceId 写入待监控设备列表
 */
void add_device_id(int device_id)
{
    device_list[device_nums] = device_id;
    device_nums++;
}

/**
 * @brief 从设备列表中删除设备id
 */
void remove_device_id(int device_id)
{
    int i;
    for (i = 0; i < device_nums; i++)
    {
        if (device_list[i] == device_id)
        {
            // 用后面的元素 覆盖掉当前元素
            memmove(&device_list[i], &device_list[i + 1], device_nums - i - 1);
            device_nums--;
            return;
        }
    }
}

/**
 * @brief 下行通路 后半程 由线程池完成
 * 1  从下行缓冲提取数据
 * 2  把数据写发送到modbus 2条   速度+ 开关
 * 3  把设备id写入 设备监控列表
 */
static void *down2_writeModbus(void *arg)
{
    // * 1  从下行缓冲提取数据
    char data_buff[10];
    app_buffer_read(down_buffer, data_buff, 10);
    // * 2  把数据写发送到modbus 2条   速度+ 开关
    uint8_t device_id = data_buff[0];
    uint16_t motor_set_nums = 0;
    memcpy(&motor_set_nums, data_buff + 1, 2);
    uint8_t motor_status = data_buff[3];
    app_modbus_writeHoldingRegister(device_id, 2, 1, &motor_set_nums); // 速度

    app_modbus_writeCoil(device_id, 2, 1, &motor_status); // 开关
    // * 3  把设备id写入 设备监控列表
    add_device_id(device_id);

    return NULL;
}

/**
 * @brief 接收mqtt消息的回调
 * //1  把接收的json转换
//  //2 写入下行缓冲
   //3 提交后续任务给线程池
 */
int down1_mqtt_messageCallback(char *message_payload)
{
    // 1  把接收的json转换
    char data_buff[10];
    int data_len = message_jsonToChars(message_payload, data_buff, 10);
    if (data_len <= 0)
    {
        return -1;
    }
    // 2 写入下行缓冲
    int ret = app_buffer_write(down_buffer, data_buff, data_len);
    if (ret < 0)
    {
        return -1;
    }
    // 3 提交后续任务给线程池
    app_pool_submitTask(down2_writeModbus, NULL);

    return 0;
}

/**
 * @brief 上行数据处理 由线程池完成  上行通路 下半部分
 * 1 从缓冲区提取数据
 * 2 转换为json
 * 3 发送mqtt
 * 4 如果电机状态为关 从设备列表中删除该设备
 */
static void *up2_sendMqttMsg(void *arg)
{
    //    * 1 从缓冲区提取数据
    char data_buff[4];
    app_buffer_read(up_buffer, data_buff, 4);

    //    * 2 转换为json
    char *json = message_charsToJson(data_buff, 4);

    //    * 3 发送mqtt
    app_mqtt_sendMessage(json);
    cJSON_free(json);
    //    * 4 如果电机状态为关 从设备列表中删除该设备
    uint8_t motor_status = data_buff[3];
    uint8_t device_id = data_buff[0];
    if (motor_status == 0)
    {
        remove_device_id(device_id);
    }
    return NULL;
}

/**
 * @brief  扫描设备列表 并 查询设备的数值   上行通信 上半部分
 * 1 扫描设备列表
 * 2   如果有需要检查的设备   对该设备发送 modbus的读指令
 *      3  数值组合后放入缓冲区
 *     4 向线程池提交后续的任务
 */
static void *up1_checkDeviceAndReadModbus(void *arg)
{
    while (1)
    {
        for (int i = 0; i < device_nums; i++)
        {
            //   对该设备发送 modbus的读指令
            uint8_t device_id = device_list[i];
            uint8_t motor_cur_status = 0;
            uint16_t motor_speed = 0;
            app_modbus_readCoil(device_id, 2, 1, &motor_cur_status);
            app_modbus_readInputRegister(device_id, 2, 1, &motor_speed);
            //  数值组合后放入缓冲区
            uint8_t data_buff[4];
            data_buff[0] = device_id;
            memcpy(data_buff + 1, &motor_speed, 2);
            data_buff[3] = motor_cur_status;
            app_buffer_write(up_buffer, (char *)data_buff, 4);

            // 向线程池提交后续的任务
            app_pool_submitTask(up2_sendMqttMsg, NULL);
        }
        sleep(1);
    }
    return NULL;
}

/**
 * @brief 设备模块启动
 * 1  向mqtt 注册回调  下行通路 起点
 * 2  启动线程 扫描监控设备列表
 */
int app_device_start(void)
{
    //  * 1  向mqtt 注册回调  下行通路 起点
    app_mqtt_registerMessageCallback(down1_mqtt_messageCallback);
    //  * 2  启动线程 扫描监控设备列表  上行通路 起点
    pthread_create(&device_check_thread, NULL, up1_checkDeviceAndReadModbus, NULL);

    log_info("app_device_start..............");

    return 0;
}

/**
 * @brief 设备模块销毁
 */
void app_device_destroy(void);